#[derive(Debug, Clone, Copy)]
struct Point {
    x: i32,
    y: i32,
}

// 有字符串类型的值，或者说有分配在堆上的数据，那么这个结构体就不具备Copy特质，需要实现Copy就必须把String类型的字段改为&str类型，但需要手动支持生命周期来保证正确性
#[derive(Debug, Clone, Copy)]
struct Book<'a> {
    name: &'a str,
    price: i32,
}

//
#[derive(Debug, Clone)]
struct Car {
    name: String,
    price: i32,
}

fn main() {
    // Copy
    // 基础类型、数组、元组和结构体，都是分配在栈上(内存中)，除结构体都具有copy特质(结构体是分配在栈上，但是Move操作)
    let a = 1;
    println!("a: {}", a);
    let b = a;
    println!("a: {}, b: {}", a, b);

    let arr1 = [2; 0];
    println!("arr1: {:?}", arr1);
    let arr2 = arr1;
    println!("arr1: {:?}, arr2: {:?}", arr1, arr2);

    let p1 = Point { x: 1, y: 2 };
    println!("p1: {:?}", p1);
    let p2 = p1;
    // 在Point没有实现clone和Copy特质时，下面的p1是不可用的，因为p1没有copy操作，验证了结构体是move操作，但又是分配在栈上的
    println!("p1: {:?}, p2: {:?}", p1, p2);

    // 带有&str类型的结构体，通过对结构体实现Copy特质和生命周期支持，来实现Copy能力
    let b1 = Book {
        name: "Rust",
        price: 100,
    };
    println!("b1: {:?}", b1);
    let b2 = b1;
    println!("b1: {:?}, b2: {:?}", b1, b2);

    // 带有String类型的字段，通过clone()方法调用，实现Copy能力（更推荐这种来复制数据）
    let c1 = Car {
        name: String::from("Rust"),
        price: 100,
    };
    println!("c1: {:?}", c1);
    let c2 = c1.clone();
    println!("c1: {:?}, c2: {:?}", c1, c2);

    // 引用具有Copy特质
    let c1 = Car {
        name: String::from("XiaoMi"),
        price: 230_000,
    };
    let c2 = &c1;
    println!("c1: {:?}, c2: {:?}", c1, c2);

    // Move
    // String、Vec、Box、Cow等类型，是分配在堆上，都是move操作
    let s1 = String::from("Rust");
    println!("s1: {}", s1);
    let s2 = s1;
    // println!("s1: {}, s2: {}", s1, s2);
    let s1 = s2.clone();
    println!("s1: {}, s2: {}", s1, s2);

    let v1 = vec![1, 2, 3];
    println!("v1: {:?}", v1);
    let v2 = v1;
    // 下面的v1所有权交出去了，不能被使用打印
    // println!("v1: {:?}, v2: {:?}", v1, v2);
    let v1 = v2.clone();
    // 使用了clone()，实现了数据复制 
    println!("v1: {:?}, v2: {:?}", v1, v2);
}
